package com.zzyl.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.NursingPlanDto;
import com.zzyl.dto.NursingProjectPlanDto;
import com.zzyl.entity.NursingPlan;
import com.zzyl.entity.NursingProject;
import com.zzyl.entity.NursingProjectPlan;
import com.zzyl.mapper.NursingPlanMapper;
import com.zzyl.mapper.NursingProjectMapper;
import com.zzyl.service.NursingPlanService;
import com.zzyl.vo.NursingPlanVo;
import com.zzyl.vo.NursingProjectPlanVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class NursingPlanServiceImpl implements NursingPlanService {
    LocalDateTime now = LocalDateTime.now();
    @Autowired
    private NursingPlanMapper nursingPlanMapper;
    @Autowired
    private NursingProjectMapper nursingProjectMapper;

    @Override
    public PageResponse<NursingPlanVo> getByPage(String name, Integer status, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<NursingPlan> nursingPlans = nursingPlanMapper.selectByPage(name, status);
        PageResponse<NursingPlanVo> nursingPlanVoPageResponse = PageResponse.of(nursingPlans, NursingPlanVo.class);
        return nursingPlanVoPageResponse;
    }

    @Transactional
    @Override
    public void add(NursingPlanDto nursingPlanDTO) {
        log.info(">> add事务开始");
        System.out.println(nursingPlanDTO);

        // 转换DTO到Entity
        NursingPlan nursingPlan = convertDtoToEntity(nursingPlanDTO);
        System.out.println(nursingPlan);

        nursingPlan.setStatus(1);

        // 关键修复：初始化空集合
        if (nursingPlan.getProjectPlans() == null) {
            nursingPlan.setProjectPlans(new ArrayList<>());
        }

        // 1. 插入主表
        nursingPlanMapper.insert(nursingPlan); // 审计字段由拦截器填充
        // 此时plan.getId()已自动填充为数据库生成的主键

        // 2. 插入关联表
        // 现在可以安全遍历（即使空集合也不会NPE）
        for (NursingProjectPlan project : nursingPlan.getProjectPlans()) {
            project.setPlanId(nursingPlan.getId());
            // 移除手动设置的审计字段：createBy, createTime, updateBy, updateTime
            NursingProject existing = nursingProjectMapper.selectById(project.getId());
            if (existing != null) {
                project.setProjectName(existing.getName());
            }
        }

        // 空集合时batchInsert不会执行SQL
        if (!nursingPlan.getProjectPlans().isEmpty()) {
            // 批量插入，拦截器会自动填充审计字段
            nursingPlanMapper.batchInsertProjectPlans(nursingPlan.getProjectPlans());
        }
        log.info("<< add事务提交");
    }


    @Override
    public List<NursingPlanVo> getAll() {
        List<NursingPlan> nursingPlans = nursingPlanMapper.selectList();

        // 转换为 Vo 对象
        return nursingPlans.stream()
                .map(nursingPlan -> {
                    NursingPlanVo vo = new NursingPlanVo();
                    // 复制属性
                    BeanUtils.copyProperties(nursingPlan, vo);
                    return vo;
                })
                .collect(Collectors.toList());
    }

    @Override
    public NursingPlanVo getById(Long id) {
        // 1. 查询护理计划实体
        NursingPlan nursingPlan = nursingPlanMapper.selectById(id);
        if (nursingPlan == null) {
            System.out.println("护理计划不存在");
        }
        System.out.println(nursingPlan);

        // 2. 手动转换VO对象
        NursingPlanVo vo = new NursingPlanVo();
        vo.setId(nursingPlan.getId());
        vo.setSortNo(nursingPlan.getSortNo());
        vo.setPlanName(nursingPlan.getPlanName());
        vo.setStatus(nursingPlan.getStatus());
        vo.setCreateBy(nursingPlan.getCreateBy());
        vo.setCreateTime(nursingPlan.getCreateTime());
        vo.setUpdateBy(nursingPlan.getUpdateBy());
        vo.setUpdateTime(nursingPlan.getUpdateTime());
        vo.setRemark(nursingPlan.getRemark());

        // 3. 转换关联的项目计划
        if (nursingPlan.getProjectPlans() != null && !nursingPlan.getProjectPlans().isEmpty()) {
            List<NursingProjectPlanVo> projectVos = nursingPlan.getProjectPlans().stream()
                    .map(project -> {
                        NursingProjectPlanVo projectVo = new NursingProjectPlanVo();
                        projectVo.setId(project.getId());
                        projectVo.setPlanId(project.getPlanId());
                        projectVo.setProjectId(project.getProjectId());
                        projectVo.setExecuteTime(project.getExecuteTime());
                        projectVo.setExecuteCycle(project.getExecuteCycle());
                        projectVo.setExecuteFrequency(project.getExecuteFrequency());
                        projectVo.setCreateBy(project.getCreateBy());
                        projectVo.setCreateTime(project.getCreateTime());
                        projectVo.setUpdateBy(project.getUpdateBy());
                        projectVo.setUpdateTime(project.getUpdateTime());
                        projectVo.setRemark(project.getRemark());
                        projectVo.setProjectName(project.getProjectName());
                        return projectVo;
                    })
                    .collect(Collectors.toList());
            vo.setProjectPlans(projectVos);

            // 设置count
            vo.setCount(projectVos.size());
        } else {
            vo.setCount(0);
            vo.setProjectPlans(Collections.emptyList());
        }

        System.out.println(vo);

        return vo;
    }

    @Transactional
    @Override
    public void update(NursingPlanDto nursingPlanDTO) throws NotFoundException {
        log.info(">> update事务开始");

        // 1. 先查询出原有的护理计划
        NursingPlan existingPlan = nursingPlanMapper.selectById(nursingPlanDTO.getId());
        if (existingPlan == null) {
            throw new NotFoundException("护理计划不存在");
        }

        System.out.println(nursingPlanDTO);

        // 转换DTO到Entity
        NursingPlan nursingPlan = convertDtoToEntity(nursingPlanDTO);
        System.out.println(nursingPlan);

        // 1. 修改主表
        nursingPlanMapper.update(nursingPlan); // 审计字段由拦截器填充
        // 此时plan.getId()已自动填充为数据库生成的主键

        // 3. 处理关联表 - 先查询出现有项目关联
        List<NursingProjectPlan> existingProjects = nursingPlanMapper.selectProjectPlansByPlanId(nursingPlan.getId());
        Map<Long, NursingProjectPlan> existingProjectMap = existingProjects.stream()
                .collect(Collectors.toMap(NursingProjectPlan::getId, Function.identity()));

        // 2. 修改关联表
        // 现在可以安全遍历（即使空集合也不会NPE）
        for (NursingProjectPlan project : nursingPlan.getProjectPlans()) {
            project.setPlanId(nursingPlan.getId());
            // 设置项目名称
            if (project.getProjectId() != null) {
                NursingProject projectInfo = nursingProjectMapper.selectById(project.getProjectId());
                if (projectInfo != null) {
                    project.setProjectName(projectInfo.getName());
                }
            }

            // 判断是更新还是新增
            if (project.getId() != null) {
                // 更新操作：保持原有的create_time和create_by
                NursingProjectPlan existingProject = existingProjectMap.get(project.getId());
                if (existingProject != null) {
                    project.setCreateTime(existingProject.getCreateTime());
                    project.setCreateBy(existingProject.getCreateBy());
                }
            } else {
                // 新增操作：设置新的create_time和create_by 由拦截器完成
            }
        }

        // 5. 批量更新关联表（使用ON DUPLICATE KEY UPDATE）
        if (!nursingPlan.getProjectPlans().isEmpty()) {
            nursingPlanMapper.batchUpdateProjectPlans(nursingPlan.getProjectPlans());
        }
        log.info("<< update事务提交");
    }

    @Transactional
    @Override
    public void deleteById(Long id) throws NotFoundException {
        log.info(">> delete事务开始");

        // 1. 先删除关联表数据（避免外键约束冲突）
        nursingPlanMapper.deleteProjectPlansByPlanId(id);

        // 2. 再删除主表数据
        int result = nursingPlanMapper.deleteById(id);

        if (result == 0) {
            throw new NotFoundException("护理计划不存在");
        }

        log.info("<< delete事务提交");
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        nursingPlanMapper.updateStatusById(id, status);
    }

    // DTO 转 Entity 的专用方法
    private NursingPlan convertDtoToEntity(NursingPlanDto dto) {
        NursingPlan entity = new NursingPlan();
        BeanUtils.copyProperties(dto, entity);

        // 转换关联集合
        List<NursingProjectPlan> projects = new ArrayList<>();
        if (dto.getProjectPlans() != null) {
            for (NursingProjectPlanDto planDto : dto.getProjectPlans()) {
                NursingProjectPlan project = new NursingProjectPlan();
                BeanUtils.copyProperties(planDto, project);

                // 确保 projectId 正确转换
                if (planDto.getProjectId() != null) {
                    project.setProjectId(Long.parseLong(planDto.getProjectId().toString()));
                }

                projects.add(project);
            }
        }
        entity.setProjectPlans(projects);

        return entity;
    }

}
